package com.xh.demo.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xh.demo.common.consts.ConfigConst;
import com.xh.demo.common.utils.DateUtil;
import com.xh.demo.config.custom.CustomDateConverter;
import com.xh.demo.config.custom.CustomJsonDateDeserializer;
import com.xh.demo.config.custom.MyRequesrBodyResolver;
import com.xh.demo.config.custom.UserVoArgumentResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @Name WebMvcConfig
 * @Description spring-mvc配置
 * @Author wen
 * @Date 2019-07-31
 */
@Configuration
@EnableWebMvc   //开启SpiingMVC定制配置功能（<mvc:annotation-driven />）
@ComponentScan(basePackages = {"com.xh.demo"}, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {})
}, useDefaultFilters = false)   //只包含需要禁用默认扫描规则，排除不需要
public class WebMvcConfig implements WebMvcConfigurer {

    @Bean
    public Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean() {
        Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean();
        jackson2ObjectMapperFactoryBean.setDeserializers(new CustomJsonDateDeserializer());
        return jackson2ObjectMapperFactoryBean;
    }

    /**
     * 解决中文乱码
     **/
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        return new StringHttpMessageConverter(Charset.forName(ConfigConst.DEFAULT_CHARSET_ENCODING_UTF8));
    }

    /**
     * 解决对象json数据转换异常
     **/
    @Bean
    public HttpMessageConverter messageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setDateFormat(DateUtil.formarters[0]);
        converter.setObjectMapper(objectMapper);
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        converter.setSupportedMediaTypes(supportedMediaTypes);
        return converter;
    }

    /** 添加到类型转换配置 **/
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //解决中文乱码
        converters.add(responseBodyConverter());
        //解决对象json数据转换异常HttpMessageNotWritableException：No converter found for return value of type: class com.xh.demo.xxx
        converters.add(messageConverter());
    }

    /**
     * 视图解析器
     **/
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix(ConfigConst.DEFAULT_JSP_ACCESS_PREFIX);
        resolver.setSuffix(ConfigConst.DEFAULT_JSP_ACCESS_SUFFIX);
        return resolver;
    }

    /** 文件上传配置**/
    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setDefaultEncoding(ConfigConst.DEFAULT_CHARSET_ENCODING_UTF8);
        resolver.setMaxInMemorySize(ConfigConst.MAX_IN_MEMORY_SIZE);
        resolver.setMaxUploadSizePerFile(ConfigConst.MAX_UPLOAD_SIZE_PERFILE);
        resolver.setMaxUploadSize(ConfigConst.MAX_UPLOAD_SIZE);
        return resolver;
    }

    /** 开启略过静态资源（<mvc:default-servlet-handler/>） **/
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /** 定制前端传入的日期字符串格式转为Date **/
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new CustomDateConverter());
    }

    /** 自定义MVC参数解析器 **/
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new UserVoArgumentResolver());
        List<HttpMessageConverter<?>> converters = new ArrayList<>();
        //添加消息转换器
        converters.add(messageConverter());
        //消息转换器与Resolver绑定
        resolvers.add(new MyRequesrBodyResolver(converters));
    }

    /**
     * 设置统一错误处理要跳转的视图
     */
//     @Bean
//     public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
//      SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
//      Properties properties = new Properties();
//       properties.getProperty("java.lang.Exception", "error");
//     simpleMappingExceptionResolver.setExceptionMappings(properties);
//    return simpleMappingExceptionResolver;
//   }

}
